package com.autonavi.yunda.yunji.core.engine.argresolver;

import com.autonavi.yunda.yunji.common.utils.JsonUtils;
import com.autonavi.yunda.yunji.core.enums.ParamSourceType;
import com.autonavi.yunda.yunji.core.enums.ParamType;
import com.autonavi.yunda.yunji.core.utils.ValidUtil;
import com.autonavi.yunda.yunji.core.vo.HttpRequest;
import com.autonavi.yunda.yunji.core.vo.param.Param;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.collections.MapUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.util.MultiValueMap;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.Map;

import static org.springframework.web.bind.annotation.ValueConstants.DEFAULT_NONE;

/**
 * @author cizhong.wcs
 * @date 2022/6/2 14:15
 */
public class BodyParamResolver implements ParamResolver {
    @Override
    public boolean supportsParam(Param param) {
        return ParamSourceType.body.equals(param.source);
    }

    private Object getFileByName(MultiValueMap<String, MultipartFile> multiValueMap, String name) {
        if (multiValueMap == null || multiValueMap.get(name) == null) {
            return null;
        }
        return multiValueMap.get(name).get(0);
    }

    @Override
    public Object resolve(HttpRequest request, Param param) {
        String body = request.getBody();
        MultiValueMap<String, MultipartFile> multiFileMap = request.getMultiFileMap();
        if (Strings.isBlank(body) && MapUtils.isEmpty(multiFileMap) && !DEFAULT_NONE.equals(param.defaultVal)) {
            return param.defaultVal;
        }
        Map<String, Object> bodyMap = Strings.isBlank(body) ? new HashMap<>(8) : JsonUtils.from(body, new TypeReference<>() {
        });
        Object arg;
        if (ParamType.FILE.getCode().equals(param.type)) {
            arg = getFileByName(multiFileMap, param.name);
        } else {
            arg = bodyMap.get(param.name);
        }
        if (arg == null && !DEFAULT_NONE.equals(param.defaultVal)) {
            arg = param.defaultVal;
        }
        if (param.require) {
            ValidUtil.notBlank(param.getName(), arg);
        }
        return arg;
    }
}
